<?php

// Controller

class Ctrl{

    public $action = '';
    public $mkvs = [];
    public $data = [];

    function __construct($mkvs=[]){
        if(!empty($mkvs)){
            $this->_init($mkvs); 
        }
    }

    // 初始化方法, 如果需要, 重写此方法
    function _init($mkvs){
        global $_cbase; $_cbase['mkvs'] = $mkvs;
        $this->mkvs = $mkvs;
        if(in_array($mkvs['type'],['home','view'])){
            $func0 = '_'.$mkvs['type'].'Act';
            $act = method_exists($this, $func0) ? $func0 : '';
        }else{
            $f1 = $mkvs['key'].'Act'; $f2 = '_listAct';
            if(substr($f1,0,1)<'A'){ $f1 = "_$f1"; } // 数字开头加`_`, eg:_911Act
            $act = method_exists($this,$f1) ? $f1 : (method_exists($this,$f2) ? $f2 : '');
        }
        $this->action = $act;
    }

    // 执行方法
    function doAction(){
        $this->doStart(); 
        if($this->action){
            $action = $this->action; 
            $this->$action(); 
        }elseif(vmode()=='tpl'){
            $this->tpl();
        }else{ // api
            $vx = $this->mkvs; 
            $msg = "Action `$vx[part]:$vx[mod]Ctrl.$vx[key]Act` NOT Found!";
            $this->api([], 'NO-Action', $msg, 601);
        }
        $this->doEnd();
    }
    // 前置处理-如权限认证; 如果需要, 重写此方法
    function doStart(){} 
    // 后置处理-如写日志; 如果需要, 重写此方法
    function doEnd(){} 

    // api输出
    function api($data, $errno=0, $errmsg='', $state=200){
        $data['_info'] = ['errno'=>$errno, 'errmsg'=>$errmsg];
        $this->vjson($data, $state);
    }
    // 提示(模板)输出
    function tip($data, $errno=0, $errmsg='', $state=200, $tpl=''){
        if(is_string($data) && !$errmsg){ // 最简单只一个str参数
            $errmsg = $data;
        }else{ // data一般为空吧, 除非用于调试
            $this->data['_trace'] = $data;
        }
        $_info = ['errno'=>$errno, 'errmsg'=>$errmsg, 'state'=>$state];
        $tpl = $tpl ? tpl_path($tpl) : 'root/_pub/info.htm';
        $this->vtpl($tpl, $_info, $state);
    }
    // 模板输出
    function tpl($data=[], $tpl='', $state=200){
        if($tpl){
            $tpl = tpl_path($tpl, 0); $notpl[] = $tpl; // + htm/xml
            $tpfile = file_exists(DIR_THEME."/$tpl") ? $tpl : '';
        }else{
            $tab = ['tpone','tpdef'];
            foreach($tab as $tpk){
                if(empty($this->mkvs[$tpk])){ continue; }
                $tpl = tpl_path($this->mkvs[$tpk], 0); $notpl[] = $tpl;
                $tpfile = file_exists(DIR_THEME."/$tpl") ? $tpl : '';
                if($tpfile){ break; }
                elseif(!empty($this->mkvs['view'])){ 
                    $vfix = ($this->mkvs['type']=='list'?'-':'.') . $this->mkvs['view']; 
                    $tpl = str_replace($vfix, '', $tpl);
                    if(file_exists(DIR_THEME."/$tpl")){ $tpfile = $tpl; break; }
                }
            }
        }
        // _info & display
        if(!$tpfile){ 
            $state = 404; // $notpl = mod-xxx, mod-_list
            $_info = ['errno'=>"NO-Template", 'errmsg'=>"Template `{$notpl[0]}` NOT Found!"];
        }
        $this->data = $data; $_info['state'] = $state;
        if(!$tpfile || $state!=200){ $tpfile = "root/_pub/info.htm"; }
        $this->vtpl($tpfile, $_info, $state);
    }
    // 包含区块, refp:1-返回路径, array-携带数据
    function inc($tpl, $refp=0){
        $tpfile = tpl_path($tpl, 0); //echo $tpfile;
        if(file_exists(DIR_THEME."/$tpfile")){
            if(!empty($refp) && is_array($refp)){
                extract($refp, EXTR_OVERWRITE);
                include DIR_THEME."/$tpfile";
            }elseif(!empty($refp)){
                return DIR_THEME."/$tpfile"; 
            }else{
                $this->vtpl($tpfile, [], 0);
            } 
        }else{
            echo "<!--(Include `$tpfile` NOT Found!)-->";
        }
    }

    // 错误处理:Error-info
    function error($ex, $type='Debug') {
        $tres = Debug::trace(5, $ex, $type); $vmode = vmode();
        $trace = $tres['tab']; $info = $tres['info']; 
        $_info = ['errno'=>"error:".$info['type'], 'errmsg'=>$info['errmsg']];
        if($vmode=='api'){ // api
            $data = ['_info'=>$_info, '_trace'=>$trace];
            $this->vjson($data, 601); 
        }elseif($vmode=='tpl'){ // tpl
            $this->data['_trace'] = $trace;
            $this->vtpl('root/_pub/info.htm', $_info, 500); // 500/404
        }else{ // -
            Http::status(404);
            $errmsg = Basic::filText(urldecode($_info['errmsg']));
            echo "\n<p><b>$_info[errno]</b><br>$errmsg</p>\n";
            Debug::vdump([$trace]);
        }
    }
    // json-显示
    function vjson($data, $state=200){
        if(uval('debug')){
            $data['_debug'] = Debug::bugInfo();
            $mode = JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT;
        }else{
            $mode = JSON_UNESCAPED_UNICODE;
        }
        if($state!=200){ Http::status($state); }
        header('content-type:application/json');
        $jsonStr = json_encode($data, $mode);
        echo $jsonStr;
    }
    // html/xml-显示
    function vtpl($tpfile, $_info=[], $state=200){
        global $_cbase; # _info, $this->data, $this->mkvs
        if($state){
            if($state!=200){ Http::status($state); }
            $type = substr($tpfile,-4)=='.xml' ? 'xml' : 'html';
            header("content-type:text/$type; charset=utf-8");
        }
        if(empty($this->mkvs)){ $this->mkvs=$_cbase['mkvs']; }
        extract($this->data, EXTR_OVERWRITE);
        include DIR_THEME."/$tpfile";
    }
    
}
